package com.mebs.edi.parser.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
 * Utility functions for Class conversion
 * 
 * @author nit
 * @version 1.0
 *
 */
public class ClassUtils {
	
	private static SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd");
	private static SimpleDateFormat timeParser = new SimpleDateFormat("HH:mm:ss");
	
	/**
	 * 
	 * Converts a String into desired class
	 * 
	 * @param s
	 * @param c
	 * @return class instance 
	 * @throws ParseException 
	 *  
	 */
	public static Object convertStringToClass(String s, Class c) throws ParseException {
		// TODO: this probably needs to be more sophisticated
		if (c == String.class) {
			return s;
		} else if (c == Character.class) {
			if (s.length() > 0) {
			 	return Character.valueOf(s.charAt(0));
			} else {
				return Character.valueOf('\u0000');
			}
		} else if (c == Byte.class) {
			return Byte.valueOf(s);
		} else if (c == Short.class) {
			return Short.valueOf(s);
		} else if (c == Integer.class) {
			return Integer.valueOf(s);
		} else if (c == Long.class) {
			return Long.valueOf(s);
		} else if (c == Float.class) {
			return Float.valueOf(s);
		} else if (c == Date.class) {
			return dateParser.parse(s);
		} else if (c == Time.class) {
			Date d = timeParser.parse(s);
			Time t = new Time(d.getTime());
			return t;
		} else {
			throw new UnsupportedOperationException("Cannot convert \"" + s + "\" to " + c.getSimpleName() + 
					". Only String, Character, Byte, Short, Integer, Long, Float, Date and Time are supported");
		}
	}
	
	public static String getSetterName(Field f) {
		String fieldName = f.getName();
		return "set" + StringUtils.capitalize(fieldName);
	}
	
	public static String getGetterName(Field f) {
		String fieldName = f.getName();
		return "get" + StringUtils.capitalize(fieldName);
	}
	
	public static Method getSetterMethod(Field f, Class c) throws SecurityException, NoSuchMethodException {
		String setterMethodName = getSetterName(f);
		Class setterParameterClass = f.getType();
		
		Method setterMethod = c.getMethod(setterMethodName, setterParameterClass);
		
		return setterMethod;
	}
	
	public static Method getGetterMethod(Field f, Class c) throws SecurityException, NoSuchMethodException {
		String getterMethodName = getGetterName(f);
		Method getterMethod = c.getMethod(getterMethodName);
		
		return getterMethod;
	}
	
	public static Object getFieldValue(Field field, Object object) 
		throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Class objectClass = object.getClass();
		Method valueGetterMethod = ClassUtils.getGetterMethod(field, objectClass);
		Object fieldValue = valueGetterMethod.invoke(object);
		return fieldValue;
	}
}
